package mware_lib.namensdienst;

import java.io.IOException;

import java.util.Hashtable;
import mware_lib.namensdienst.communication.ObjectConnection;
import mware_lib.namensdienst.communication.Server;
import mware_lib.namensdienst.messages.*;

public class Namensdienst implements Runnable {

	public static int NAMENSDIENSTPORT = 55553;
	public static String NAMENSDIENSTHOST = "localhost";

	private boolean running;
	private Server server;
	private ObjectConnection myConnection;

	private Hashtable<String, DataPack> nameReferenzen;

	public Namensdienst(){
		nameReferenzen = new Hashtable<String, DataPack>();
		running = true;

		try {
			server = new Server(NAMENSDIENSTPORT);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public Object empfangen(Object msg){
		if(msg instanceof ResolveMsg){
			ResolveMsg res = (ResolveMsg)msg;

			//System.out.println("################################################################################## ResolveMsg: " + res.getID());

			if(nameReferenzen.containsKey(res.getID())){
				DataPack data = nameReferenzen.get(res.getID());
				ResolveBackMsg resBack = new ResolveBackMsg(data.getHost(), data.getPort(), data.getType());
				return resBack;
			}else{
				//System.out.println("Key in nameReferenzen nicht vorhanden");
				return (new ResolveBackMsg(null, 0, null));
			}

		}else if(msg instanceof RebindMsg){
			RebindMsg res = (RebindMsg)msg;

			//System.out.println("RebindMsg erhalten!");

			boolean erfolg = false;

			if((res.getLocalPort() != 0) && (res.getLocalHost() != null)){
				//neuen Eintrag erstellen mit ID, ...
				String objectType = "";
				if(res.getType().equals("Account")){
					objectType = "Account";
				}else if(res.getType().equals("Manager")){
					objectType = "Manager";
				}else{
					System.out.println("Namensdienst.empfangen -> RebindMsg -> objectType nicht bekannt!!");
				}

				System.out.println("Namensdienst: " + objectType + " wurde in nameReferenzen gepackt.");
				nameReferenzen.put(res.getID(), new DataPack(res.getLocalHost(), res.getLocalPort(), objectType));
				erfolg = true;
			}else{
				//L�schen des Eintrags mit der ID
				if(nameReferenzen.containsKey(res.getID())){
					nameReferenzen.remove(res.getID());
					erfolg = true;
				}else{
					System.out.println("Rebind entfernen: Konto garnicht vorhanden");
					erfolg = false;
				}
			}
			return new RebindBackMsg(erfolg);
		}else{
			//System.out.println("Namensdienst.empfangen -> weder Rebind noch ResolveMsg. -> uebelster Fehler");
			return null;
		}

	}

	public void run() {

		while(running){
			try {
				myConnection = server.getConnection();
				// Kommunikation
				try {

					//System.out.println("Warte auf Nachricht");
					Object msg =  myConnection.receive();
					//System.out.println("msg: " + msg);

					Object returnMsg = empfangen(msg);


					myConnection.send(returnMsg);

					//System.out.println("FERTIG");

				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}

				// Verbindung schliessen
				myConnection.close();
				//System.out.println("Verbindung geschlossen");

			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	public static void main(String[] args) throws IOException {

		if (args.length>1 && !args[0].equals("--help")) {
			NAMENSDIENSTHOST = args[0];
			NAMENSDIENSTPORT = Integer.parseInt(args[1]);


			Namensdienst n = new Namensdienst();
			Thread t = new Thread(n);
			t.start();
		} else {
			System.err.println("Usage: java mware_lib/namensdienst/Namensdienst <name-service-host> <name-service-port>");
		}
	}


}
